package com.fitz.remote.codec;

import com.fitz.remote.model.BasicObject;
import com.fitz.serializer.HessianSerializer;
import com.fitz.serializer.JSONSerializer;
import com.fitz.serializer.KryoSerializer;
import com.fitz.serializer.Serializer;
import io.netty.buffer.ByteBuf;

import java.util.HashMap;
import java.util.Map;

/**
 * @author fitz 2020-5-6 20:33
 */
public class Codec {
    private static final int MAGIC_NUMBER = 0x123456;

    private final Map<Byte, Serializer> serializerMap = new HashMap<>();

    public static final Codec INSTANCE = new Codec();

    private Serializer getSerializer(byte serializerType){
        return serializerMap.get(serializerType);
    }

    private Codec() {
        Serializer jsonSerializer = new JSONSerializer();
        Serializer hessianSerializer = new HessianSerializer();
        Serializer kryoSerializer = new KryoSerializer();
        serializerMap.put(kryoSerializer.getSerializerType(),kryoSerializer);
        serializerMap.put(jsonSerializer.getSerializerType(),jsonSerializer);
        serializerMap.put(hessianSerializer.getSerializerType(),hessianSerializer);
    }

    public void encode(Object msg, ByteBuf out,byte serializerType){
        Serializer serializer = getSerializer(serializerType);
        byte[] bytes = serializer.serialize(msg);
        out.writeInt(MAGIC_NUMBER);
        out.writeInt(bytes.length);
        out.writeBytes(bytes);
    }

    public <T> T decode(ByteBuf buf,byte serializerType,Class<? extends BasicObject> clazz){
        int magicNumber = buf.readInt();
        if (magicNumber != MAGIC_NUMBER){
            return null;
        }
        int length = buf.readInt();
        byte[] bytes = new byte[length];
        buf.readBytes(bytes);
        Serializer serializer = getSerializer(serializerType);
        T t = (T) serializer.deSerialize(clazz,bytes);
        return t;
    }
}
